# -*- coding: UTF-8 -*-

from datetime import datetime
import sys
from sqlalchemy import and_,  func, or_
from typing import Dict, List, Any, Generator

from sqlalchemy import Boolean, Column, DateTime, Integer, String, Index, Table, ForeignKey, text, JSON, TEXT, distinct
from sqlalchemy.orm import Session, relationship
from common.database import Base
from common.database import SessionMixin
from common.utils import is_empty
from core.logger import logger

__all__ = ['BillEvent']

class BillEvent(Base, SessionMixin):
    '''
    资产事件记录
    '''
    __tablename__ = "bill_event"
    name = Column(String(256), nullable=False, comment='事件名称')
    bill_cycle = Column(String(64), nullable=False, index=True, comment='账期')
    cloud_platform = Column(String(64), comment='云平台')
    # 自定义事件、工单事件
    event_type = Column(String(128), nullable=False, index=True, comment='事件类别')
    relation_id = Column(String(128), nullable=True, default="", comment='关联事件id')
    # 实例id、实例名称、产品名称、appname标签值
    info_type = Column(String(128), nullable=False, index=True, comment='信息类别')
    info_items = Column(JSON, nullable=False, default=[], comment='信息条目')

    update_at = Column(DateTime, default=datetime.now, onupdate=datetime.now, comment='更新时间')
    comment = Column(String(256), nullable=True, comment='事件说明')



    __table_args__ = (
        {
            'mysql_engine': 'innodb',
            'mysql_charset': 'utf8mb4',
            'mysql_collate': 'utf8mb4_unicode_ci',
            'extend_existing': True,
            'mysql_row_format': 'dynamic'
        }
    )

    def __repr__(self):
        return f"<event_name={self.name}>"


    def object_to_dict(self, db: Session):
        result = {
            key: getattr(self, key)
            for key in self.__mapper__.c.keys()
        }
        return result



    @classmethod
    def get_object_by_relation_id(cls, db: Session, bill_cycle: str, relation_id: str):
        object = db.query(cls).filter(
            cls.bill_cycle == bill_cycle,
            cls.relation_id == relation_id
        ).first()
        return object



    @classmethod
    def get_object_by_item(cls, db: Session, bill_cycle: str, cloud_platform: str, info_type: str, info_item: str):
        object = db.query(cls).filter(
            cls.bill_cycle == bill_cycle,
            cls.cloud_platform == cloud_platform,
            cls.info_type == info_type,
            func.json_contains(cls.info_items, str(info_item)) == 1
        ).first()
        return object


    @classmethod
    def get_object_info_by_item(cls, db: Session, bill_cycle: str, cloud_platform: str, info_type: str, info_item: str):
        # cls.info_items.contains(info_item)
        search_field = [func.json_contains(cls.info_items, f'\"{info_item}\"') == 1]
        if bill_cycle: search_field.append(cls.bill_cycle == bill_cycle)
        if cloud_platform: search_field.append(cls.cloud_platform == cloud_platform)
        if info_type: search_field.append(cls.info_type == info_type)
            
        object_infos = db.query(cls).filter(
            and_(*search_field)
        ).to_dict()
        return object_infos
